package cn.cew.bytespy.transfer;

import cn.cew.bytespy.comm.AgentContextCache;
import cn.cew.bytespy.comm.AgentParam;
import cn.cew.bytespy.utils.BaseUtils;
import javassist.CannotCompileException;

import java.io.IOException;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import java.text.MessageFormat;

/**
 * @author chenenwei
 * @version 1.0.0
 * @description TODO
 * @createTime 2022-10-15 13:32:00
 */
public abstract class BaseTransformer implements ClassFileTransformer {

    public AgentParam agentParam;

    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {

        String originClass = BaseUtils.packageToDot(className);

        // 缓存原class
        AgentContextCache.addOriginalBytesCache(originClass, classfileBuffer);

        try {
            if (agentParam.isCreateProxy()) {
                return makeClass(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
            }
            return doTransform(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public abstract  byte[] doTransform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws Exception;

    public abstract  byte[] makeClass(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws Exception;

    /**
     * 构建发送方法
     * @param msg
     * @return
     */
    public String makeSend (String msg) {

        return MessageFormat.format("ByteSpySocketClient.send(" +  "\"{0}\"" + "," + "\"{1}\"" + ", {2});", agentParam.getIp(), String.valueOf(agentParam.getPort()), msg);
    }

    public String makeMethodMsg (String methodName, String type, String data) {

        return MessageFormat.format("\"[{0}] \" + {1}", methodName + "@" + type, data);
    }

    public String makeVarMsg (String methodName, String varName, String type, String data) {

        return MessageFormat.format("\"[{0}] \" + {1}", methodName + "@" + varName + "@" + type, data);

    }
}
